package com.demo.test.leak

import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.base.tool.log.LogPrint
import com.fortest.R
import com.demo.component.LeakingSingleton2
import kotlinx.android.synthetic.main.activity_leak_dialog_listener.*

/**
泄露方式：单例
泄露原因：
LeakingSingleton2是个单例，其生命周期比Activity长。
在Activity中设置所定义的监听是一个匿名内部类，默认持有Activity的引用，而这个监听被LeakingSingleton2单例长期持有，
因此即使Activity已经退出了，Activity仍然被单例所引用着，得不到释放。

泄露报告　－－　StrictMode：
2020-05-24 19:43:34.357 3221-3221/com.example.myapplication E/StrictMode: class com.demo.test.leak.ActivityLeakD_Instance_Listener; instances=2; limit=1
android.os.StrictMode$InstanceCountViolation: class com.demo.test.leak.ActivityLeakD_Instance_Listener; instances=2; limit=1
at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)

泄露报告　－－　LeakCanary：
15757 bytes retained by leaking objects
Signature: 48e9cc286127d2eee686eb71e7374c32d879856
┬───
│ GC Root: System class
│
├─ com.demo.component.LeakingSingleton2$SingleTonHolder class
│    Leaking: NO (a class is never leaking)
│    ↓ static LeakingSingleton2$SingleTonHolder.INSTANCE
│                                               ~~~~~~~~
├─ com.demo.component.LeakingSingleton2 instance
│    Leaking: UNKNOWN
│    ↓ LeakingSingleton2.deniedListener
│                        ~~~~~~~~~~~~~~
├─ com.demo.test.leak.ActivityLeakD_Instance_Listener$onCreate$1$1 instance
│    Leaking: UNKNOWN
│    Anonymous subclass of kotlin.jvm.internal.Lambda
│    ↓ ActivityLeakD_Instance_Listener$onCreate$1$1.this$0
│                                                   ~~~~~~
├─ com.demo.test.leak.ActivityLeakD_Instance_Listener$onCreate$1 instance
│    Leaking: UNKNOWN
│    Anonymous class implementing android.view.View$OnClickListener
│    ↓ ActivityLeakD_Instance_Listener$onCreate$1.this$0
│                                                 ~~~~~~
╰→ com.demo.test.leak.ActivityLeakD_Instance_Listener instance
​     Leaking: YES (ObjectWatcher was watching this because com.demo.test.leak.ActivityLeakD_Instance_Listener received Activity#onDestroy() callback and Activity#mDestroyed is true)
​     key = e9d29050-3d68-40dd-9436-7c3b11317343
​     watchDurationMillis = 16610
​     retainedDurationMillis = 11609
 **/
class ActivityLeakD_Instance_Listener : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_leak_dialog_listener)
        val textView = findViewById<TextView>(R.id.helper_text)
        textView.text = "LeakingSingleton2是个单例，其生命周期比Activity长。\n" +
                "在Activity中设置所定义的监听是一个匿名内部类，默认持有Activity的引用，而这个监听被LeakingSingleton2单例长期持有，\n" +
                "因此即使Activity已经退出了，Activity仍然被单例所引用着，得不到释放。"
        tv_activity_leak2.setOnClickListener {
            LeakingSingleton2.instance
                .onDenied { finish() }
                .onGranted { LogPrint.e("xx", "xx"); }
                .request(this)
        }

    }

}